package it.rap.application.logic.mappers;

import it.rap.application.logic.BusinnessLogic;
import it.rap.applications.persistence.entities.filters.FilterTree;
import it.rap.applications.persistence.entities.filters.RoleTree;
import it.rap.applications.persistence.entities.movimento.Movimento;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

public class ReportLogic extends BusinnessLogic {
		
	public ReportLogic() {
		super("publisher");
	}
	
	public ReportSum crateQueryByFilter( FilterTree f ){
		CriteriaBuilder cb = enm.getCriteriaBuilder();		  
		
		CriteriaQuery<ReportSum> q = cb.createQuery(ReportSum.class);
		Root<Movimento> c = q.from(Movimento.class);
		
		Expression<BigDecimal> e1 = c.get("addebito");
		Expression<BigDecimal> e2 = c.get("accredito");
		
		q.select( cb.construct(ReportSum.class, cb.sum( e1 )  , cb.sum( e2 ) ) );
		
		List<RoleTree> rList = f.getRoleTreeList();
		List<Predicate> pList = new ArrayList<Predicate>();
		for( RoleTree r: rList ){
			if ( r.isChecked() ){
				//TODO il campo da filtrare dovrà finire nella role
				Expression<String> l1 = c.get("descrizioneCompleta");
				//Ogni Filtro rppresenta un predicato le regole di un filtro sono in and
				if ( r.getSubRoleTreeList() != null && r.getSubRoleTreeList().size() > 0  ){
					List<Predicate> pOrList = new ArrayList<Predicate>();
					for( RoleTree subR: r.getSubRoleTreeList() ){
						if ( subR.isChecked() ){
							Predicate p =  cb.like( l1, "%" + subR.getRegexpPattern() + "%" );
							pOrList.add( p );
						}
					}
					Predicate p =  cb.like( l1, "%" + r.getRegexpPattern() + "%" );
					pOrList.add( p );
					if ( pOrList.size() > 0 ){
						pList.add( cb.or( pOrList.toArray( new Predicate[ pOrList.size() ] ) ) );
					}
				} else {
					//TODO il tipo operazione deve finire nella role
					Predicate p =  cb.like( l1, "%" + r.getRegexpPattern() + "%" );
					
					pList.add( p );
				}
			}
		}

		Predicate[] lP = pList.toArray( new Predicate[ pList.size() ]);
		
		q.where( cb.or( lP ) );
		
		TypedQuery<ReportSum> typedQuery = enm.createQuery( q );
		
		ReportSum su = typedQuery.getSingleResult();
		
		System.out.println("RESULT: " + su.getAccredito() + " : " + su.getDebito() );
		return su;
	}
	
}
